package com.tender.desensitization.converters;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.tender.desensitization.dto.SecretResponseDTO;
import com.tender.properties.AppConfigProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.tender.utils.AESUtil;
import com.tender.utils.RSAUtil;
import com.tender.utils.SecretContextUtil;
import com.tender.exceptions.CommonException;

import java.util.Base64;

import static com.tender.enums.ErrorTypeEnum.ENCRYPT_DATA_2_RETURN_FRONT;

@Slf4j
@Component
public class EncryptionConverter {

    private final Base64.Encoder base64Encoder = Base64.getEncoder();
    private final Base64.Decoder base64Decoder = Base64.getDecoder();

    @Autowired
    private AppConfigProperties configProperties;

    public SecretResponseDTO encryptionAllResponse(Object data) {
        SecretResponseDTO responseDTO = new SecretResponseDTO();
        String keyAES128 = null;
        byte[] ivBytes = null;
        try {
            keyAES128 = configProperties.isFixedAes() ? configProperties.getKeyAES128() : AESUtil.getKeyAES_128();
            ivBytes = configProperties.isFixedAes() ? base64Decoder.decode(configProperties.getIvAES()) : AESUtil.generateIV();
            responseDTO.setSecretAES128(RSAUtil.encryptWithPrivateKey(keyAES128, configProperties.getPrivateKeyStr()));
        } catch (Exception e) {
            log.error("【数据加密失败】具体的数据 result = {}", JSON.toJSONString(data));
            log.error("【数据加密失败】具体的 keyAES128 = {}", keyAES128);
            log.error("【数据加密失败】具体的 ivBytes = {}", null != ivBytes ? base64Encoder.encodeToString(ivBytes) : null);
            throw new CommonException(ENCRYPT_DATA_2_RETURN_FRONT);
        }
        responseDTO.setIvAES(base64Encoder.encodeToString(ivBytes));
        responseDTO.setKeyAES128(configProperties.isDevEnv() ? configProperties.getKeyAES128() : null);
        String resultStr = String.class != data.getClass()
                ? JSON.toJSONString(data, SerializerFeature.WriteNullStringAsEmpty)  // 部分接口有特殊要求，要求显示字段。
                : (String) data;
        // 返回给前端的内容，需要 AES 加密返回
        if (configProperties.isUseIvAES()) {
            responseDTO.setData(AESUtil.encrypt(keyAES128, resultStr, ivBytes));
        } else {
            responseDTO.setData(AESUtil.encrypt(keyAES128, resultStr, null));
        }

        return responseDTO;
    }

    public SecretResponseDTO wrapResponseData(Object data) {
        SecretContextUtil.SecretContext secretContext = SecretContextUtil.getSecretContext();
        // 如果对字段进行加密处理了，则 secretContext 不为 null
        if (null != secretContext) {
            SecretResponseDTO responseVO = new SecretResponseDTO();
            responseVO.setData(JSON.toJSONString(data));
            responseVO.setIvAES(secretContext.getIvAES());
            responseVO.setSecretAES128(secretContext.getSecretAES128());
            responseVO.setKeyAES128(secretContext.getKeyAES128());

            return responseVO;
        }

        return null;
    }

}
